package com.zmn.oms.zmn.business.impl.wallquotation;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.zmn.base.common.data.common.dro.fault.FaultDRO;
import com.zmn.base.common.data.dubbo.interfaces.fault.FaultListRemoteService;
import com.zmn.base.pilot.common.dto.pilot.PilotCheckQuery;
import com.zmn.base.pilot.common.enums.PilotTypeEnum;
import com.zmn.base.pilot.dubbo.interfaces.pilot.PilotRemoteService;
import com.zmn.base.plat.engine.common.constant.PlatEngineConsts;
import com.zmn.base.price.common.dro.item.ItemAdditionDRO;
import com.zmn.base.price.common.dro.item.ItemDRO2;
import com.zmn.base.price.common.dro.item.ItemTypeDRO;
import com.zmn.base.price.dubbo.interfaces.item.ItemAdditionRemoteService;
import com.zmn.base.price.dubbo.interfaces.item.ItemRemoteService;
import com.zmn.base.price.dubbo.interfaces.item.ItemTypeRemoteService;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.categ.serv.CategServProductListRemoteService;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.base.shortlink.common.constant.DubboConsts;
import com.zmn.base.shortlink.dubbo.interfaces.shortlink.ShortLinkModifyRemoteService;
import com.zmn.coa.common.dio.ItemInfoDIO;
import com.zmn.coa.common.dio.OrderItemTwoPriceAmountDIO;
import com.zmn.coa.common.dio.ProductBaseInfoDIO;
import com.zmn.coa.common.dro.OrderItemDiscountDRO;
import com.zmn.coa.common.dro.OrderItemTwoPriceAmountDRO;
import com.zmn.coa.dubbo.impl.interfaces.amount.OrderAmountRemoteService;
import com.zmn.common.constant.StatusConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.dms.common.enums.DiscountTypeEnums;
import com.zmn.manager.mq.constant.MqTopicConsts;
import com.zmn.manager.mq.interfaces.MessageDelayTimeEnum;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.oms.business.interfaces.conf.attachment.ConfOrderAttachmentBService;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.masterphoto.OrderPhotoBService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageGetSendInfoService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageSendBaseService;
import com.zmn.oms.business.interfaces.orderamount.OrderAmountCalcBService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dio.wallquotation.WallDiscountDIO;
import com.zmn.oms.common.dio.wallquotation.WallOrderAmountDIO;
import com.zmn.oms.common.dio.wallquotation.WallQuotationDIO;
import com.zmn.oms.common.dio.wallquotation.WallQuotationDetailDIO;
import com.zmn.oms.common.dro.wallquotation.*;
import com.zmn.oms.common.enums.ServiceItemTypeEnum;
import com.zmn.oms.common.enums.WallTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.orderamount.ReCalcOrderAmountDIO;
import com.zmn.oms.model.dto.messageV1.SmsMessageDTO;
import com.zmn.oms.model.dto.messageV1.WeChatMessageDTO;
import com.zmn.oms.model.dto.serviceitem.AddOrderServiceItemDTO;
import com.zmn.oms.model.dto.work.masterwork.ModifyProductDTO;
import com.zmn.oms.model.dto.work.modify.amount.ZsDiscountDTO;
import com.zmn.oms.model.entity.conf.attachment.ConfOrderAttachment;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.orderattachment.OrderAttachment;
import com.zmn.oms.model.entity.orderattachment.OrderAttachmentQuery;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.product.OrderProductExtend;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.walldiscount.WallDiscount;
import com.zmn.oms.model.entity.wallquotation.WallQuotation;
import com.zmn.oms.model.entity.wallquotation.WallQuotationQuery;
import com.zmn.oms.model.entity.wallservitem.WallServItem;
import com.zmn.oms.model.entity.wallservitem.WallServItemQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.orderattachment.OrderAttachmentService;
import com.zmn.oms.services.interfaces.product.OrderProductExtendService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.walldiscount.WallDiscountService;
import com.zmn.oms.services.interfaces.wallquotation.WallQuotationService;
import com.zmn.oms.services.interfaces.wallservitem.WallServItemService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.wallquotation.WallQuotationBService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkModifyProductBService;
import com.zmn.oms.zmn.normal.business.interfaces.discount.ZsNormalOrderDiscountBService;
import com.zmn.oms.zmn.normal.business.interfaces.serviceitem.ZsNormalOrderServiceItemBService;
import com.zmn.performance.common.enums.OrderTimeoutTypeEnum;
import com.zmn.performance.dubbo.interfaces.order.OrderTimeoutWarningListRemoteService;
import com.zmn.saas.common.dto.wechat.WeixinUserInfoDRO;
import com.zmn.saas.dubbo.interfaces.qrcode.PrivateQrCodeListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.junit.Assert;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static com.zmn.oms.common.constant.OrderConsts.SERVICE_ITEM_TYPE_FAULT;

/**
 * 墙面订单业务实现类
 *
 * @author chengguang
 * @date 2022/05/24
 */
@Service
@Slf4j
public class WallQuotationBServiceImpl implements WallQuotationBService {

    @Resource
    private OrderWorkService orderWorkService;

    @Resource
    private WallServItemService wallServItemService;

    @Resource
    private WallQuotationService wallQuotationService;

    @Resource
    private WallDiscountService wallDiscountService;

    @Resource
    private OrderProductService orderProductService;

    @Resource
    private OrderDetailService orderDetailService;

    @Resource
    private MessageGetSendInfoService messageGetSendInfoService;

    @Resource
    private MessageSendBaseService messageSendBaseService;

    @Resource
    private ZsNormalOrderDiscountBService normalOrderDiscountBService;

    @Resource
    private OrderLogBService orderLogBService;

    @Resource
    private OrderWorkModifyProductBService orderWorkModifyProductBService;

    @Resource
    private ZsNormalOrderServiceItemBService zsNormalOrderServiceItemBService;

    @Resource
    private OrderProductExtendService orderProductExtendService;

    @Resource
    private OrderAttachmentService orderAttachmentService;

    @Resource
    private ConfOrderAttachmentBService confOrderAttachmentBService;

    @Resource
    private OrderPhotoBService orderPhotoBService;

    @Resource
    private OrderAmountCalcBService orderAmountCalcBService;

    @Resource(name = "wallQuotationThreadPool", type = ThreadPoolTaskExecutor.class)
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private FaultListRemoteService faultListRemoteService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private PilotRemoteService pilotRemoteService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private CategServProductListRemoteService categServProductListRemoteService;

    @DubboReference(version = com.zmn.coa.common.util.DubboConsts.INTERFACE_VERSION, check = false)
    private OrderAmountRemoteService orderAmountRemoteService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ItemRemoteService itemRemoteService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ItemAdditionRemoteService itemAdditionRemoteService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ItemTypeRemoteService itemTypeRemoteService;

    @DubboReference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private ShortLinkModifyRemoteService shortLinkModifyRemoteService;

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ProductForeignListRemoteService productForeignListRemoteService;

    @DubboReference(version = com.zmn.saas.dubbo.constant.SaasDubboConsts.INTERFACE_VERSION, check = false)
    private PrivateQrCodeListRemoteService privateQrCodeListRemoteService;

    @DubboReference(version = com.zmn.performance.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private OrderTimeoutWarningListRemoteService orderTimeoutWarningListService;

    @Resource
    private ZmnMQSender zmnMQSender;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @NacosValue(value = "${h5.wall.quotation.confirmUrl:https://test2-h5.xiujiadian.com/wxuser/brand/#/subPackages/order/acceptance/confirmPrice?orderId=%s&pageType=confirm&workId=%s}", autoRefreshed = true)
    private String confirmUrl;

    /**
     * 墙面组id
     */
    private final static Integer WALL_GROUP_ID = 1003;

    /**
     * 防水补漏组id
     */
    private final static Integer WALL_WATERPROOF_GROUP_ID = 1000;

    @Override
    public WallQuotationServItemDRO getWallQuotationServItemByOrderIdAndWorkId(Long orderId, Long workId) throws OmsBaseException {

        // 获取coa价格
        OrderItemTwoPriceAmountDRO wallOrderPriceAmount = getWallOrderPriceAmount(orderId, workId);
        WallQuotation wallQuotation = wallQuotationService.findById(workId);

        // 服务项附加项图标
        List<WallServItem> wallServItems = wallServItemService.listByQuery(WallServItemQuery.builder().workId(orderId).build());
        List<Integer> itemIds = new ArrayList<>();
        List<Integer> additionIds = new ArrayList<>();
        wallServItems.forEach(wallServItem -> {
            if (Objects.equals(wallServItem.getServItemType(), WallItemTypeEnum.SERV_ITEM.getCode())) {
                itemIds.add(wallServItem.getServItemId());
            }
            if (Objects.equals(wallServItem.getServItemType(), WallItemTypeEnum.Addition_ITEM.getCode())) {
                additionIds.add(wallServItem.getServItemId());
            }
        });
        List<ItemDRO2> itemDRO2s = resultToThrow(() -> itemRemoteService.listByIds(itemIds));
        List<ServItemBaseDRO> servItemBases = BeanUtil.copyToList(itemDRO2s, ServItemBaseDRO.class);
        if (CollectionUtil.isNotEmpty(additionIds)) {
            List<ItemAdditionDRO> itemAdditions = resultToThrow(() -> itemAdditionRemoteService.listByIds(additionIds));
            List<ServItemBaseDRO> collect = itemAdditions.stream().map(itemAdditionDRO ->
                    ServItemBaseDRO.builder()
                            .itemId(itemAdditionDRO.getItemAdditionId())
                            .itemName(itemAdditionDRO.getItemAdditionName())
                            .build()
            ).collect(Collectors.toList());
            servItemBases.addAll(collect);
        }

        return WallQuotationServItemDRO.builder()
                .orderId(orderId)
                .wallStatus(wallQuotation.getWallStatus())
                .payPrice(wallOrderPriceAmount.getAmountPrice())
                .servItemBases(servItemBases)
                .build();
    }

    @Override
    public WallQuotationDetailDRO getWallQuotationDetailByOrderIdAndWorkId(Long orderId, Long workId) throws OmsBaseException {

        List<WallQuotation> wallQuotations = wallQuotationService.listByQuery(WallQuotationQuery.builder().orderId(orderId).workId(workId).build());
        if (CollectionUtil.isEmpty(wallQuotations)) {
            return null;
        }
        WallQuotation wallQuotation = wallQuotations.get(GlobalConsts.NONE);
        List<WallServItem> wallServItems = wallServItemService.listByQuery(WallServItemQuery.builder().workId(workId).build());
        List<WallServItemDRO> wallServItemDROS = BeanUtil.copyToList(wallServItems, WallServItemDRO.class);
        WallQuotationDetailDRO wallQuotationDetailDRO = BeanUtil.copyProperties(wallQuotation, WallQuotationDetailDRO.class);
        if (StringUtils.isNotEmpty(wallQuotation.getFault())) {
            wallQuotationDetailDRO.setFaultIds(Arrays.stream(wallQuotation.getFault().split(","))
                    .map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList()));
        }
        wallQuotationDetailDRO.setWallServItems(wallServItemDROS);
        return wallQuotationDetailDRO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addWallQuotationDetail(WallQuotationDetailDIO wallQuotationDetailDIO) throws Exception {

        addEditWallQuotationDetail(wallQuotationDetailDIO);
        threadPoolTaskExecutor.execute(() -> {
            try {
                sendWallQuotationToUser(wallQuotationDetailDIO.getOrderId(), wallQuotationDetailDIO.getWorkId(), wallQuotationDetailDIO.getProductName());
            } catch (Exception e) {
                log.error("墙面报价给用户发送消息失败：{}", e.getMessage(), e);
            }
        });

        // 发送延时消息，自动确认报价
        WallQuotationDIO wallQuotationDIO = BeanUtil.copyProperties(wallQuotationDetailDIO, WallQuotationDIO.class);
        wallQuotationDIO.setPayPrice(wallQuotationDetailDIO.getAmountPrice());
        zmnMQSender.sendWithDelayTime(MqTopicConsts.ZMN_TOPIC_OMS, MessageQueueTagConsts.WALL_ORDER_AUTOMATIC_CONFIRMATION_TAG,
                MessageQueueTagConsts.WALL_ORDER_AUTOMATIC_CONFIRMATION_TAG + wallQuotationDetailDIO.getOrderId(),
                JSON.toJSONString(wallQuotationDIO), MessageDelayTimeEnum.DELAY_TIME_1m);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean confirmWallQuotation(WallQuotationDIO wallQuotationDIO) throws OmsBaseException {

        Long orderId = wallQuotationDIO.getOrderId();
        Long workId = wallQuotationDIO.getWorkId();

        String key = String.format(RedisKeyConsts.OMS_CONFIRM_WALL_QUOTATION, workId);
        String redisWorkId = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(redisWorkId)) {
            throw new OmsBaseException("请等一等再点击");
        }
        // 存入redis保证幂等性
        redisTemplate.opsForValue().set(key, String.valueOf(workId), 10, TimeUnit.SECONDS);

        // 获取暂存表墙面订单详细信息
        WallQuotationDetailDRO wallQuotationDetail = getWallQuotationDetailByOrderIdAndWorkId(orderId, workId);

        OrderItemTwoPriceAmountDRO wallOrderPriceAmount = getWallOrderPriceAmount(orderId, workId);
        if (!Objects.equals(wallQuotationDIO.getPayPrice(), wallOrderPriceAmount.getAmountPrice())) {
            throw new OmsBaseException("价格有误");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        Long operatorId = wallQuotationDIO.getOperatorId();
        String operator = wallQuotationDIO.getOperator();
        Integer operatorType = wallQuotationDIO.getOperatorType();

        // 基础附件项/服务项转换oms订单服务项
        List<OrderServiceItem> orderServiceItems = new ArrayList<>();
        List<WallServItemDRO> wallServItems = wallQuotationDetail.getWallServItems();
        List<Integer> servItemIds = new ArrayList<>();
        List<Integer> itemAdditionIds = new ArrayList<>();
        wallServItems.forEach(wallServItemDRO -> {
            if (Objects.equals(wallServItemDRO.getServItemType(), WallItemTypeEnum.SERV_ITEM.getCode())) {
                servItemIds.add(wallServItemDRO.getServItemId());
            } else {
                itemAdditionIds.add(wallServItemDRO.getServItemId());
            }
        });

        Map<Integer, ItemAdditionDRO> itemAdditionDROMap = null;
        if (CollectionUtil.isNotEmpty(itemAdditionIds)) {
            List<ItemAdditionDRO> itemAdditionDROS = resultToThrow(() -> itemAdditionRemoteService.listByIds(itemAdditionIds));
            itemAdditionDROMap = itemAdditionDROS.stream().collect(Collectors.toMap(ItemAdditionDRO::getItemAdditionId, Function.identity()));
        }

        List<ItemDRO2> itemDRO2s = resultToThrow(() -> itemRemoteService.listByIds(servItemIds));
        Map<Integer, ItemDRO2> itemDRO2Map = itemDRO2s.stream().collect(Collectors.toMap(ItemDRO2::getItemId, Function.identity()));
        List<Integer> itemTypeIds = itemDRO2s.stream().map(ItemDRO2::getItemTypeId).collect(Collectors.toList());
        List<ItemTypeDRO> itemTypes = resultToThrow(() -> itemTypeRemoteService.listByIds(itemTypeIds));
        Map<Integer, ItemTypeDRO> itemTypeDROMap = itemTypes.stream().collect(Collectors.toMap(ItemTypeDRO::getItemTypeId, Function.identity()));
        Map<Integer, ItemAdditionDRO> finalItemAdditionDROMap = itemAdditionDROMap;
        wallServItems.forEach(wallServItemDRO -> {
            if (Objects.equals(wallServItemDRO.getServItemType(), WallItemTypeEnum.SERV_ITEM.getCode())) {
                ItemDRO2 itemDRO2 = itemDRO2Map.get(wallServItemDRO.getServItemId());
                Assert.assertNotNull("servItemId:" + wallServItemDRO.getServItemId() + "查询不到数据", itemDRO2);
                OrderServiceItem orderServiceItem = new OrderServiceItem();
                orderServiceItem.setOrderId(orderId);
                orderServiceItem.setProductId(wallQuotationDetail.getProductId());
                orderServiceItem.setServItemId(itemDRO2.getItemId());
                orderServiceItem.setServItemName(itemDRO2.getItemName());
                orderServiceItem.setServItemGroupId(itemDRO2.getItemTypeId());
                ItemTypeDRO itemTypeDRO = itemTypeDROMap.get(itemDRO2.getItemTypeId());
                Assert.assertNotNull(itemTypeDRO);
                orderServiceItem.setServItemGroupName(itemTypeDRO.getItemTypeName());
                orderServiceItem.setServItemCategId(itemDRO2.getItemTypeId());
                orderServiceItem.setNumber(wallServItemDRO.getServItemSize());
                orderServiceItem.setItemPrice(wallServItemDRO.getServItemPrice());
                orderServiceItem.setCreater(operator);
                orderServiceItem.setCreateTime(new Date());
                orderServiceItems.add(orderServiceItem);
            } else {
                assert finalItemAdditionDROMap != null;
                ItemAdditionDRO itemAdditionDRO = finalItemAdditionDROMap.get(wallServItemDRO.getServItemId());
                OrderServiceItem orderServiceItem = new OrderServiceItem();
                orderServiceItem.setServItemId(itemAdditionDRO.getItemAdditionId());
                orderServiceItem.setServItemName(itemAdditionDRO.getItemAdditionName());
                orderServiceItem.setItemPrice(wallServItemDRO.getServItemPrice());
                orderServiceItem.setNumber(wallServItemDRO.getServItemSize());
                orderServiceItem.setServItemGroupId(ServiceItemTypeEnum.ADDITION_ITEM.getType());
                orderServiceItem.setServItemGroupName(ServiceItemTypeEnum.ADDITION_ITEM.getName());
                orderServiceItem.setServItemCategId(ServiceItemTypeEnum.ADDITION_ITEM.getType());
                orderServiceItem.setCreater(operator);
                orderServiceItem.setCreateTime(new Date());
                orderServiceItems.add(orderServiceItem);
            }
        });


        /**
         * 抽空写个新的方法
         * 修改产品 调用 com.zmn.oms.zmn.business.impl.work.OrderWorkModifyProductBServiceImpl#updateOrderProduct(com.zmn.oms.model.dto.work.masterwork.ModifyProductDTO)
         * 修改服务项 调用 com.zmn.oms.zmn.normal.business.impl.serviceitem.ZsNormalOrderServiceItemBServiceImpl#saveServiceitem(com.zmn.oms.model.dto.serviceitem.AddOrderServiceItemDTO)
         */
        if (!Objects.equals(wallQuotationDetail.getProductId(), orderWork.getProductId())) {
            ModifyProductDTO modifyProductDTO = BeanUtil.copyProperties(wallQuotationDIO, ModifyProductDTO.class);
            modifyProductDTO.setMasterId(orderWork.getMasterId());
            modifyProductDTO.setProductId(wallQuotationDetail.getProductId());
            modifyProductDTO.setServItemType(SERVICE_ITEM_TYPE_FAULT);
            //修改产品
            orderWorkModifyProductBService.updateOrderProduct(modifyProductDTO);
        }


        //修改服务项
        AddOrderServiceItemDTO addOrderServiceItemDTO = BeanUtil.copyProperties(wallQuotationDIO, AddOrderServiceItemDTO.class);
        List<OrderProductExtend> extendList = orderProductExtendService.listByOrderId(orderId);
        if (CollectionUtil.isEmpty(extendList)) {
            throw new OmsBaseException("工单产品扩张数据为空");
        }
        Long proExtId = extendList.get(0).getProExtId();
        addOrderServiceItemDTO.setProExtId(proExtId);
        addOrderServiceItemDTO.setServItemType(SERVICE_ITEM_TYPE_FAULT);
        addOrderServiceItemDTO.setQuotationType(GlobalConsts.OPERATE_USER_TYPE_USER);
        addOrderServiceItemDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_USER);
        addOrderServiceItemDTO.setOrderServiceItemList(orderServiceItems);
        addOrderServiceItemDTO.setIsWallQuotationOrder(GlobalConsts.YES);
        log.info("zsNormalOrderServiceItemBService.saveServiceitem 入参：{}", JSON.toJSONString(addOrderServiceItemDTO));
        zsNormalOrderServiceItemBService.saveServiceitem(addOrderServiceItemDTO);

        /**
         * zsOrderWorkBService.updateOrderQuotation 内部有处理人工优惠
         */
        // 保存人工优惠的
        if (Objects.nonNull(wallQuotationDetail.getLaborPreferencePrice()) && wallQuotationDetail.getLaborPreferencePrice() > 0) {
            ZsDiscountDTO zsDiscountDTO = new ZsDiscountDTO();
            zsDiscountDTO.setOrderId(orderId);
            zsDiscountDTO.setWorkId(workId);
            zsDiscountDTO.setOperateId(GlobalConsts.NONE);
            zsDiscountDTO.setOperatorId(Objects.isNull(operatorId) ? 1L : operatorId);
            zsDiscountDTO.setOperatorType(operatorType);
            zsDiscountDTO.setOperator(StringUtils.isBlank(operator) ? "系统" : operator);
            zsDiscountDTO.setDiscountAmount(wallQuotationDetail.getLaborPreferencePrice());
            normalOrderDiscountBService.saveDiscount(zsDiscountDTO, TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT);
        }
        wallQuotationService.updateByKey(WallQuotation.builder().workId(workId).wallStatus(GlobalConsts.YES).build());

        // 保存操作日志
        threadPoolTaskExecutor.execute(() -> {
            try {
                log.info("异步保存墙面报价日志开始，wallQuotationDIO：{}", JSON.toJSONString(wallQuotationDIO));
                saveWallQuotationLog(wallQuotationDIO);
            } catch (Exception e) {
                log.error("保存墙面操作日志出错：{}", e.getMessage(), e);
                e.printStackTrace();
            }
        });
        return Boolean.TRUE;
    }

    private Boolean sendWallQuotationToUser(Long orderId, Long workId, String productName) throws Exception {

        log.info("WallQuotationBServiceImpl.sendWallQuotationToUser orderId:{} workId:{} ", orderId, workId);
//        Long orderId = omsOperator.getOrderId();
//        Long workId = omsOperator.getWorkId();
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "订单不存在");
        }
        String thirdAppId = messageGetSendInfoService.getOrderWeChatThirdAppId(orderId, orderWork.getPlatWork());

        // 优先发送扫码用户
        Long sendUserId = orderWork.getVisitUserId();
        if (Objects.isNull(sendUserId)) {
            sendUserId = orderWork.getUserId();
        }
        String openId = messageGetSendInfoService.getWeChatOpenIdByUserIdAndAppId(orderId, sendUserId, thirdAppId);

        // 当前用户是否关注公众号  subscribe 这个字段，1，表示关注，0表示没关注
        boolean userSubscribe = isUserSubscribe(openId, thirdAppId);

        OrderItemTwoPriceAmountDRO wallOrderPriceAmount = getWallOrderPriceAmount(orderId, workId);
        Map<String, String> map = new HashMap<>();
        if (userSubscribe) {
            map.put("contentDetail", "点击确认服务金额是否与工程师收费一致，如发现工程师虚假收费，请在服务完成后联系平台，" +
                    "本单最高减免500元！订单号：" + orderId);
            map.put("productName", productName);
            map.put("orderId", String.valueOf(orderId));
            map.put("workId", String.valueOf(workId));
            map.put("now", DateUtil.getDateStr(new Date()));
            map.put("amountPrice", "费用总价：" + (NumberUtil.div(wallOrderPriceAmount.getAmountPrice().floatValue(), 100)));
            // 发送微信消息
            WeChatMessageDTO weChatMessageDTO = WeChatMessageDTO.builder()
                    .ruleId(MessageConsts.WALL_MSG_RULE_ID_QUOTATION)
                    .skipType(GlobalConsts.YES)
                    .params(JSON.toJSONString(map))
                    .thirdAppId(thirdAppId)
                    .openId(openId)
                    .build();
            messageSendBaseService.sendWeiXinMessage(weChatMessageDTO);
            log.info("给用户发送微信消息成功，WeChatMessageDTO:{}", JSON.toJSONString(weChatMessageDTO));
        } else {
            // 发送短信
            String mobile = messageGetSendInfoService.getUserMobileByUserId(orderId, orderWork.getUserId());
            OrderDetail detail = orderDetailService.findOrderDetailByKey(orderId);
            map.put("short_link", String.format(confirmUrl, orderId, workId));
            map.put("amountPrice", NumberUtil.div(wallOrderPriceAmount.getAmountPrice().floatValue(), 100) + "");
            map.put("orderId", String.valueOf(orderId));
            map.put("workId", String.valueOf(workId));
            messageSendBaseService.sendTextMessage(SmsMessageDTO.builder()
                    .mobile(mobile)
                    .businessId(workId)
                    .params(JSON.toJSONString(map))
                    .ruleId(MessageConsts.WALL_MSG_RULE_ID_QUOTATION)
                    .build());

            if (!Objects.equals(mobile, detail.getTelephone())) {
                messageSendBaseService.sendTextMessage(SmsMessageDTO.builder()
                        .mobile(detail.getTelephone())
                        .businessId(workId)
                        .params(JSON.toJSONString(map))
                        .ruleId(MessageConsts.WALL_MSG_RULE_ID_QUOTATION)
                        .build());
            }
            log.info("给用户发送短信消息成功，用户电话：{}，下单电话：{} ，链接地址：{}", mobile, detail.getTelephone(), String.format(confirmUrl, orderId, workId));
        }

        // 修改发送状态
        wallQuotationService.updateByKey(WallQuotation.builder().workId(workId).wallStatus(GlobalConsts.TOP_ID).build());
        return Boolean.TRUE;
    }

    @Override
    public WallTypeEnum isWallQuotation(Long orderId, Long workId) throws OmsBaseException {

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("工单id为:" + orderId + "工单不存在");
        }
        // 校验试点
        return isWallOrder(PilotCheckQuery.builder()
                .categId(orderWork.getShowCategId())
                .channelId(orderWork.getChannelId())
                .cityId(orderWork.getCityId())
                .servCategId(orderWork.getServCategId())
                .build(), orderWork.getServProductGroupId(), orderWork.getServItemType());
    }

    @Override
    public WallOrderAmountDRO getWallOrderAmount(WallOrderAmountDIO wallOrderAmountDIO) throws OmsBaseException {

        Long workId = wallOrderAmountDIO.getWorkId();
        Long orderId = wallOrderAmountDIO.getOrderId();
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "订单不存在");
        }
        List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(orderId);
        if (Objects.isNull(orderProducts)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "订单产品不存在");
        }
        OrderProduct orderProduct = orderProducts.get(GlobalConsts.NONE);

        // 计算价格
        OrderItemTwoPriceAmountDIO twoPriceAmountDIO = new OrderItemTwoPriceAmountDIO();
        twoPriceAmountDIO.setOrderId(orderId);
        setLateCompensation(orderId, orderWork, twoPriceAmountDIO);

        // 产品信息
        ProductBaseInfoDIO productBaseInfoDIO = new ProductBaseInfoDIO();
        productBaseInfoDIO.setFaultList(wallOrderAmountDIO.getFaultIds());
        productBaseInfoDIO.setProductId(wallOrderAmountDIO.getProductId());
        productBaseInfoDIO.setShowType(BaseProductConsts.ET_SHOW_TYPE);
        productBaseInfoDIO.setProductNum(GlobalConsts.TOP_ID);
        productBaseInfoDIO.setShowProductId(orderWork.getShowProductId());
        productBaseInfoDIO.setTariffId(orderProduct.getTariffId());

        List<ItemInfoDIO> itemInfos = new ArrayList<>();
        wallOrderAmountDIO.getWallServItems().forEach(wallServItemDIO -> {
            ItemInfoDIO itemInfoDIO = new ItemInfoDIO();
            itemInfoDIO.setItemId(wallServItemDIO.getServItemId());
            itemInfoDIO.setNum(wallServItemDIO.getServItemSize());
            itemInfoDIO.setItemType(wallServItemDIO.getServItemType());
            itemInfos.add(itemInfoDIO);
        });
        twoPriceAmountDIO.setUserId(orderWork.getUserId());
        productBaseInfoDIO.setItemList(itemInfos);
        twoPriceAmountDIO.setProductInfoList(Collections.singletonList(productBaseInfoDIO));
        twoPriceAmountDIO.setPlat(orderWork.getPlat());
        twoPriceAmountDIO.setInvoker(1);
        twoPriceAmountDIO.setOrderTime(orderWork.getReceiveTime());
        twoPriceAmountDIO.setCityId(orderWork.getCityId());
        twoPriceAmountDIO.setChannelId(orderWork.getChannelId());
        twoPriceAmountDIO.setTariffOnoff(GlobalConsts.YES);
        twoPriceAmountDIO.setUntariffOnoff(GlobalConsts.NO);
        twoPriceAmountDIO.setArtificialDiscountTyp(GlobalConsts.NO);
        twoPriceAmountDIO.setUnextendedWarranty(GlobalConsts.YES);
        twoPriceAmountDIO.setExtendedWarranty(GlobalConsts.NO);
        twoPriceAmountDIO.setBizType(orderWork.getBizType());
        twoPriceAmountDIO.setPromId(wallOrderAmountDIO.getPromId());
        twoPriceAmountDIO.setDiscountAmount(wallOrderAmountDIO.getDiscountAmount());

        log.info("OrderAmountRemoteService.getOrderAmountCalculation,入参{}", JSON.toJSONString(twoPriceAmountDIO));
        OrderItemTwoPriceAmountDRO orderItemTwoPriceAmountDRO = resultToThrow(() ->
                orderAmountRemoteService.getOrderAmountCalculation(twoPriceAmountDIO));
        log.info("OrderAmountRemoteService.getOrderAmountCalculation,出参{}", JSON.toJSONString(orderItemTwoPriceAmountDRO));

        WallOrderAmountDRO wallOrderAmountDRO = BeanUtil.copyProperties(orderItemTwoPriceAmountDRO, WallOrderAmountDRO.class);
        List<OrderItemDiscountDRO> itemDiscountDROList = orderItemTwoPriceAmountDRO.getItemDiscountDROList();
        if (CollectionUtil.isNotEmpty(itemDiscountDROList)) {
            List<com.zmn.oms.common.dro.wallquotation.OrderItemDiscountDRO> itemDiscounts = itemDiscountDROList.stream().map(item -> {
                com.zmn.oms.common.dro.wallquotation.OrderItemDiscountDRO itemDiscountDRO = BeanUtil.copyProperties(item,
                        com.zmn.oms.common.dro.wallquotation.OrderItemDiscountDRO.class);
                itemDiscountDRO.setDiscountName(DiscountTypeEnums.getSubName(item.getDiscountType()));
                return itemDiscountDRO;
            }).collect(Collectors.toList());
            wallOrderAmountDRO.setItemDiscountDROList(itemDiscounts);
        }
        return wallOrderAmountDRO;
    }

    private void setLateCompensation(Long orderId, OrderWork orderWork, OrderItemTwoPriceAmountDIO twoPriceAmountDIO) throws OmsBaseException {
        // 添加迟到补偿优惠活动id
        ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(orderWork);
        Integer discountActivityId = calcOrderAmountDIO.getDiscountConditionParamsDIO().getDiscountActivityId();
        log.info("#getReCalcOrderAmountDIO discountActivityId:{}", discountActivityId);
        if (Objects.nonNull(discountActivityId) && discountActivityId > 0) {
            Boolean isTimeOut = resultToThrow(() -> orderTimeoutWarningListService.checkOrderTimeoutStatus(orderId, OrderTimeoutTypeEnum.VISIT));
            log.info("#checkOrderTimeoutStatus isTimeOut:{}", isTimeOut);
            if (isTimeOut) {
                twoPriceAmountDIO.setLateCompensationId(discountActivityId);
            }
        }
    }

    /**
     * 描述: 新增或修改墙面报价单
     *
     * @param wallQuotationDetailDIO 墙面报价详细信息
     * @author chengguang
     * @since 2022/05/26
     */
    private void addEditWallQuotationDetail(WallQuotationDetailDIO wallQuotationDetailDIO) throws OmsBaseException {

        log.info("[新增或修改墙面报价单],wallQuotationDetailDIO=[{}],WallQuotationBServiceImpl." +
                "addEditWallQuotationDetail", JSON.toJSONString(wallQuotationDetailDIO));
        Long workId = wallQuotationDetailDIO.getWorkId();
        Long orderId = wallQuotationDetailDIO.getOrderId();
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "订单不存在");
        }

        // 校验试点
        WallTypeEnum wallTypeEnum = isWallOrder(PilotCheckQuery.builder()
                .categId(orderWork.getShowCategId())
                .channelId(orderWork.getChannelId())
                .cityId(orderWork.getCityId())
                .servCategId(orderWork.getServCategId())
                .pilotTypeId(PilotTypeEnum.WALL_QUOTE.getId())
                .build(), orderWork.getServProductGroupId(), orderWork.getServItemType());

        if (Objects.isNull(wallTypeEnum)) {
            throw new OmsBaseException("当前订单不满足墙面试点");
        }

        //保存墙面报价信息
        String operator = wallQuotationDetailDIO.getOperator();
        WallQuotation wallQuotation = BeanUtil.copyProperties(wallQuotationDetailDIO, WallQuotation.class);
        wallQuotation.setUpdater(operator);
        if (CollectionUtil.isNotEmpty(wallQuotationDetailDIO.getFaultIds())) {
            wallQuotation.setFault(wallQuotationDetailDIO.getFaultIds().stream().map(String::valueOf)
                    .collect(Collectors.joining(",")));
        }
        WallQuotation dbWallQuotation = wallQuotationService.findById(workId);
        wallQuotation.setWallStatus(GlobalConsts.NO);
        wallQuotation.setWallType(wallTypeEnum.getCode());
        if (Objects.nonNull(dbWallQuotation)) {
            if (com.zmn.common.utils.number.NumberUtil.isNotNullOrZero(orderWork.getDepositAmount()) &&
                    wallQuotationDetailDIO.getAmountPrice() < orderWork.getDepositAmount()) {
                throw new OmsBaseException("总价不能低于已收金额");
            }
            wallQuotationService.updateByKey(wallQuotation);
        } else {
            wallQuotation.setCreater(operator);
            wallQuotationService.insert(wallQuotation);
        }

        // 保存服务项/附加项信息
        wallServItemService.deleteByWorkId(workId);
        List<WallServItem> wallServItems = wallQuotationDetailDIO.getWallServItems().stream().map(wallServItemDIO -> {
            WallServItem wallServItem = BeanUtil.copyProperties(wallServItemDIO, WallServItem.class);
            wallServItem.setWorkId(workId);
            wallServItem.setCreater(operator);
            wallServItem.setUpdater(operator);
            return wallServItem;
        }).collect(Collectors.toList());
        wallServItemService.insertBatch(wallServItems);

        // 保存优惠信息
        wallDiscountService.deleteByWorkId(workId);
        List<WallDiscountDIO> wallDiscounts = wallQuotationDetailDIO.getWallDiscounts();
        if (CollectionUtil.isNotEmpty(wallDiscounts)) {
            List<WallDiscount> collect = wallDiscounts.stream().map(wallDiscountDIO -> {
                WallDiscount wallDiscount = BeanUtil.copyProperties(wallDiscountDIO, WallDiscount.class);
                wallDiscount.setWorkId(workId);
                return wallDiscount;
            }).collect(Collectors.toList());
            wallDiscountService.insertBatch(collect);
        }

        // 保存oms附件表报告书
        List<OrderAttachment> attachmentList = orderAttachmentService.listByOrderIdAndType(orderId, OrderAttachmentTypeEnum.BGC.getCode());
        // 是否需要自动审核
        boolean needReview = false;
        OrderAttachment awaitOperateAttachment = new OrderAttachment();
        if (CollectionUtil.isNotEmpty(attachmentList)) {
            // 修改
            log.info("orderAttachmentService.listByOrderIdAndType 出参：{}", attachmentList);
            OrderAttachment orderAttachment = attachmentList.get(0);
            awaitOperateAttachment.setType(OrderAttachmentTypeEnum.BGC.getCode());
            orderAttachment.setSrc(wallQuotationDetailDIO.getIntroductionSheetImg());
            orderAttachment.setOrderId(orderId);
            orderAttachmentService.updateByKey(orderAttachment);
        } else {
            // 新增
            // 组装查询对象
            OrderAttachmentQuery orderAttachmentQuery = OrderAttachmentQuery.builder()
                    .orderId(orderWork.getOrderId())
                    .workId(orderWork.getWorkId())
                    .type(OrderAttachmentTypeEnum.BGC.getCode())
                    .bizType(orderWork.getBizType())
                    .channelId(orderWork.getChannelId())
                    .servCategId(orderWork.getServCategId()).build();

            // 查询某个类型的照片配置
            ConfOrderAttachment attachmentConfig = confOrderAttachmentBService.getAttachmentConfigByQuery(orderAttachmentQuery);
            if (attachmentConfig == null) {
                log.info("订单号：[{}] 未查询出[type:{}]的附件配置。", orderWork.getOrderId(), OrderAttachmentTypeEnum.BGC.getCode());
            }


            awaitOperateAttachment.setType(OrderAttachmentTypeEnum.BGC.getCode());
            awaitOperateAttachment.setOrderId(orderId);
            awaitOperateAttachment.setCreater(operator);
            awaitOperateAttachment.setUpdater(operator);
            awaitOperateAttachment.setSrc(wallQuotationDetailDIO.getIntroductionSheetImg());
            needReview = Objects.nonNull(attachmentConfig) && Objects.equals(attachmentConfig.getNeedReview(), GlobalConsts.YES);
            if (needReview) {
                awaitOperateAttachment.setNeedReview(attachmentConfig.getNeedReview());
                awaitOperateAttachment.setReviewStatus(OrderConsts.IMAGE_REVIEW_STATUS_WAITING);
            } else {
                awaitOperateAttachment.setNeedReview(GlobalConsts.NO);
                awaitOperateAttachment.setReviewStatus(OrderConsts.IMAGE_REVIEW_STATUS_NO);
            }

            orderAttachmentService.insertAttachment(awaitOperateAttachment);
            log.info("照片附件操作 - 新增：{}", awaitOperateAttachment);
        }
        // 自动审核
        if (needReview) {
            orderPhotoBService.sendImageDetectionMessage(orderWork.getOrderId(), orderWork.getWorkId(), awaitOperateAttachment.getAttachmentId(),
                    awaitOperateAttachment.getType());
        }

        // 保存操作日志
        threadPoolTaskExecutor.execute(() -> {
            log.info("异步保存墙面操作日志开始");
            try {
                StringBuffer wallQuotationContent = new StringBuffer();
                if (CollectionUtil.isNotEmpty(wallQuotationDetailDIO.getFaultIds())) {
                    List<FaultDRO> faultDROS = resultToThrow(() -> faultListRemoteService.listByIds(wallQuotationDetailDIO.getFaultIds()));
                    List<String> faultNames = faultDROS.stream().map(FaultDRO::getFaultName).collect(Collectors.toList());
                    wallQuotationContent.append("故障：").append(faultNames).append("</br>");
                }
                wallQuotationContent.append("产品：").append(wallQuotationDetailDIO.getProductName()).append("</br>");
                wallQuotationContent.append("总价：").append(NumberUtil.div(wallQuotationDetailDIO.getServicePrice().floatValue(), 100)).append("</br>");
                wallQuotationDetailDIO.getWallServItems().forEach(wallServItem -> {
                    wallQuotationContent.append(Objects.equals(wallServItem.getServItemType(), WallItemTypeEnum.SERV_ITEM.getCode()) ?
                                    "服务项：" : "附加项：").append(wallServItem.getServItemName()).append(",")
                            .append("单价").append(NumberUtil.div(wallServItem.getServItemPrice().floatValue(), 100)).append("元").append(",")
                            .append("数量").append(wallServItem.getServItemSize()).append(",")
                            .append("最低价").append(NumberUtil.div(wallServItem.getPriceSaleLowest().floatValue(), 100)).append("</br>");
                });
                wallQuotationContent.append("人工优惠 ：").append(NumberUtil.div(wallQuotationDetailDIO.getLaborPreferencePrice().floatValue(), 100)).append("</br>");
                wallQuotationContent.append("最终价格 ：").append(NumberUtil.div(wallQuotationDetailDIO.getAmountPrice().floatValue(), 100)).append("</br>");
                wallQuotationContent.append("报告书图片地址 ：").append(wallQuotationDetailDIO.getIntroductionSheetImg()).append("</br>");
                OrderLog orderLog = new OrderLog();
                orderLog.setTypeName("发送报价给用户");
                orderLog.setOperatorType(wallQuotationDetailDIO.getOperatorType());
                orderLog.setOperatorId(Optional.ofNullable(wallQuotationDetailDIO.getOperatorId()).orElse(1L));
                orderLog.setOperator(Optional.ofNullable(wallQuotationDetailDIO.getOperator()).orElse("系统"));
                orderLog.setMasterId(orderWork.getMasterId());
                orderLog.setPlat(orderWork.getPlat());
                orderLog.setPlatWork(orderWork.getPlatWork());
                orderLog.setManageCompanyId(orderWork.getManageCompanyId());
                orderLog.setOrderId(orderWork.getOrderId());
                orderLog.setWorkId(orderWork.getWorkId());
                orderLog.setContent(wallQuotationContent.toString());
                orderLog.setCreateTime(DateUtil.getNow());
                orderLogBService.save(orderLog);
            } catch (OmsBaseException e) {
                log.error("异步保存新增墙面报价日志失败{}", e.getMessage(), e);
                e.printStackTrace();
            }
        });

    }

    /**
     * 描述: 检验是否为墙面订单
     *
     * @param pilotCheckQuery 试点检查查询
     * @param productGroupId  产品组id
     * @param servItemType    服务项目类型
     * @return {@link Boolean }
     * @author chengguang
     * @since 2022/06/06
     */
    @Override
    public WallTypeEnum isWallOrder(PilotCheckQuery pilotCheckQuery, Integer productGroupId, Integer servItemType) {

        try {

            log.info("pilotRemoteService.checkPilotByQuery 校验试点入参：pilotCheckQuery:{}", JSON.toJSONString(pilotCheckQuery));
            // 校验墙面试点
            pilotCheckQuery.setPilotTypeId(PilotTypeEnum.WALL_QUOTE.getId());
            Boolean wallFlag = resultToThrow(() -> pilotRemoteService.checkPilotByQuery(pilotCheckQuery));
            // 校验墙面防水试点
            pilotCheckQuery.setPilotTypeId(PilotTypeEnum.WALL_WATERPROOF.getId());
            Boolean wallWaterProofFlag = resultToThrow(() -> pilotRemoteService.checkPilotByQuery(pilotCheckQuery));
            log.info("pilotRemoteService.checkPilotByQuery 校验试点出参：wallFlag:{} wallWaterProofFlag:{}", wallFlag, wallWaterProofFlag);

            Integer categId = pilotCheckQuery.getCategId();
            Integer servCategId = pilotCheckQuery.getServCategId();

            log.info("categServProductListRemoteService.listProductGroupByServCateIdAndCategId 根据服务分类ID和前台二级产品分类ID查询产品组id集合入参：" +
                    "servCategId:{} categId:{}", servCategId, categId);
            List<Integer> productGroupIds = resultToThrow(() -> categServProductListRemoteService.
                    listProductGroupByServCateIdAndCategId(servCategId, categId, BaseProductConsts.BIZ_TYPE_C));
            log.info("categServProductListRemoteService.listProductGroupByServCateIdAndCategId 根据服务分类ID和前台二级产品分类ID查询产品组id集合出参：" +
                    "productGroupIds:{}", productGroupIds);

            if (CollectionUtil.isEmpty(productGroupIds)) {
                return null;
            }

            if (productGroupIds.contains(WALL_GROUP_ID) &&
                    Objects.equals(servItemType, SERVICE_ITEM_TYPE_FAULT) && wallFlag) {
                return WallTypeEnum.WALL_QUOTATION;
            }

            if (productGroupIds.contains(WALL_WATERPROOF_GROUP_ID) &&
                    Objects.equals(servItemType, SERVICE_ITEM_TYPE_FAULT) && wallWaterProofFlag) {
                return WallTypeEnum.WALL_WATERPROOF;
            }
            return null;
        } catch (OmsBaseException e) {
            log.error("OmsBaseException:{}", e.getMessage());
            return null;
        } catch (Exception e) {
            log.error("Exception:{}", e.getMessage());
            return null;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkUpdateWallOrder(PilotCheckQuery pilotCheckQuery, Integer productGroupId, Integer servItemType, Long workId) throws OmsBaseException {

        WallQuotation wallQuotation = wallQuotationService.findById(workId);
        if (Objects.isNull(wallQuotation)) {
            return;
        }

        // 用户已确认
        if (Objects.equals(wallQuotation.getWallStatus(), PlatEngineConsts.YES)) {
            throw new OmsBaseException("用户已确认报价，不允许修改产品");
        }

        // 用户未确认并且不满足墙面订单就删除
        WallTypeEnum wallTypeEnum = this.isWallOrder(pilotCheckQuery, productGroupId, servItemType);
        if (Objects.equals(wallQuotation.getWallStatus(), PlatEngineConsts.NO) && (Objects.isNull(wallTypeEnum))) {
            // 删除墙面报价信息
            wallQuotationService.deleteByKey(workId);
            wallServItemService.deleteByWorkId(workId);
        }
    }

    /**
     * 描述: 获取coa价格
     *
     * @param orderId 订单id
     * @param workId  工单id
     * @return {@link OrderItemTwoPriceAmountDRO }
     * @author chengguang
     * @since 2022/05/30
     */
    private OrderItemTwoPriceAmountDRO getWallOrderPriceAmount(Long orderId, Long workId) throws OmsBaseException {

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "订单不存在");
        }

        WallQuotation wallQuotation = wallQuotationService.findById(workId);
        if (Objects.isNull(wallQuotation)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "墙面订单不存在");
        }

        List<WallServItem> wallServItems = wallServItemService.listByQuery(WallServItemQuery.builder().workId(workId).build());
        if (CollectionUtil.isEmpty(wallServItems)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "墙面订单服务项不存在");
        }

        List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(orderId);
        if (CollectionUtil.isEmpty(orderProducts)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "订单产品不存在");
        }
        OrderProduct orderProduct = orderProducts.get(GlobalConsts.NONE);

        // 计算价格
        OrderItemTwoPriceAmountDIO twoPriceAmountDIO = buildDefault();
        twoPriceAmountDIO.setOrderId(orderId);
        // 添加迟到补偿优惠活动id
        setLateCompensation(orderId, orderWork, twoPriceAmountDIO);

        // 产品信息
        ProductBaseInfoDIO productBaseInfoDIO = new ProductBaseInfoDIO();
        if (StringUtils.isNotBlank(wallQuotation.getFault())) {
            productBaseInfoDIO.setFaultList(Arrays.stream(wallQuotation.getFault().split(","))
                    .map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList()));
        }
        productBaseInfoDIO.setProductId(wallQuotation.getProductId());
        productBaseInfoDIO.setShowType(BaseProductConsts.ET_SHOW_TYPE);
        productBaseInfoDIO.setProductNum(GlobalConsts.TOP_ID);
        productBaseInfoDIO.setShowProductId(orderWork.getShowProductId());
        productBaseInfoDIO.setTariffId(orderProduct.getTariffId());
        List<ItemInfoDIO> itemInfos = wallServItems.stream().map(wallServItemDIO -> {
            ItemInfoDIO itemInfoDIO = new ItemInfoDIO();
            itemInfoDIO.setItemType(wallServItemDIO.getServItemType());
            itemInfoDIO.setItemId(wallServItemDIO.getServItemId());
            itemInfoDIO.setNum(wallServItemDIO.getServItemSize());
            return itemInfoDIO;
        }).collect(Collectors.toList());
        twoPriceAmountDIO.setUserId(orderWork.getUserId());
        productBaseInfoDIO.setItemList(itemInfos);
        twoPriceAmountDIO.setProductInfoList(Collections.singletonList(productBaseInfoDIO));
        twoPriceAmountDIO.setPlat(orderWork.getPlat());
        twoPriceAmountDIO.setOrderTime(orderWork.getReceiveTime());
        twoPriceAmountDIO.setCityId(orderWork.getCityId());
        twoPriceAmountDIO.setChannelId(orderWork.getChannelId());
        twoPriceAmountDIO.setBizType(orderWork.getBizType());
        twoPriceAmountDIO.setDiscountAmount(wallQuotation.getLaborPreferencePrice());
        twoPriceAmountDIO.setArtificialDiscountTyp(GlobalConsts.NO);
        twoPriceAmountDIO.setUnextendedWarranty(GlobalConsts.YES);
        twoPriceAmountDIO.setExtendedWarranty(GlobalConsts.NO);

        log.info("OrderAmountRemoteService.getOrderAmountCalculation,入参{}", JSON.toJSONString(twoPriceAmountDIO));
        OrderItemTwoPriceAmountDRO orderItemTwoPriceAmountDRO = resultToThrow(() ->
                orderAmountRemoteService.getOrderAmountCalculation(twoPriceAmountDIO));
        log.info("OrderAmountRemoteService.getOrderAmountCalculation,出参{}", JSON.toJSONString(orderItemTwoPriceAmountDRO));
        return orderItemTwoPriceAmountDRO;
    }

    /**
     * 描述: 保存墙面报价日志
     *
     * @param wallQuotationDIO 日志信息
     * @author chengguang
     * @since 2022/06/09
     */
    private void saveWallQuotationLog(WallQuotationDIO wallQuotationDIO) throws OmsBaseException {

        Long orderId = wallQuotationDIO.getOrderId();
        Long workId = wallQuotationDIO.getWorkId();
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        OrderItemTwoPriceAmountDRO wallOrderPriceAmount = getWallOrderPriceAmount(orderId, workId);
        WallQuotationDetailDRO wallQuotationDetail = getWallQuotationDetailByOrderIdAndWorkId(orderId, workId);

        StringBuffer sb = new StringBuffer();
        List<Integer> faultIds = wallQuotationDetail.getFaultIds();
        if (CollectionUtil.isNotEmpty(faultIds)) {
            List<FaultDRO> faults = resultToThrow(() -> faultListRemoteService.listByIds(faultIds));
            List<String> faultNames = faults.stream().map(FaultDRO::getFaultName).collect(Collectors.toList());
            sb.append("故障：").append(faultNames).append("<br>");
        }

        List<ProductBaseDRO> productBaseDROS = resultToThrow(() -> productForeignListRemoteService
                .listBaseDROByQuery(ProductBaseQuery.builder().showType(BaseProductConsts.ERP_SHOW_TYPE)
                        .productId(wallQuotationDetail.getProductId()).build()));
        if (CollectionUtil.isNotEmpty(productBaseDROS)) {
            sb.append("产品：").append(productBaseDROS.get(0).getProductName()).append("<br>");
        }
        sb.append("总价：").append(NumberUtil.div(wallOrderPriceAmount.getServicePrice().floatValue(), 100)).append("<br>");
        List<WallServItemDRO> wallServItems = wallQuotationDetail.getWallServItems();

        List<Integer> servItemIds = new ArrayList<>();
        List<Integer> additionItemIds = new ArrayList<>();
        wallServItems.forEach(wallServItemDRO -> {
            if (Objects.equals(wallServItemDRO.getServItemType(), WallItemTypeEnum.SERV_ITEM.getCode())) {
                servItemIds.add(wallServItemDRO.getServItemId());
            } else {
                additionItemIds.add(wallServItemDRO.getServItemId());
            }
        });
        List<ItemAdditionDRO> itemAdditions = new ArrayList<>();
        List<ItemDRO2> itemDRO2s = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(additionItemIds)) {
            itemAdditions = resultToThrow(() -> itemAdditionRemoteService.listByIds(additionItemIds));
        }

        if (CollectionUtil.isNotEmpty(servItemIds)) {
            itemDRO2s = resultToThrow(() -> itemRemoteService.listByIds(servItemIds));
        }

        Map<Integer, ItemAdditionDRO> additionDROMap = itemAdditions.stream()
                .collect(Collectors.toMap(ItemAdditionDRO::getItemAdditionId, Function.identity()));
        Map<Integer, ItemDRO2> itemDRO2Map = itemDRO2s.stream().collect(Collectors.toMap(ItemDRO2::getItemId, Function.identity()));

        wallServItems.forEach(wallServItemDRO -> {
            String itemName;
            Integer servItemId = wallServItemDRO.getServItemId();
            ItemDRO2 itemDRO2 = itemDRO2Map.get(servItemId);
            if (Objects.equals(wallServItemDRO.getServItemType(), WallItemTypeEnum.SERV_ITEM.getCode())) {
                itemName = itemDRO2.getItemName();
            } else {
                ItemAdditionDRO itemAdditionDRO = additionDROMap.get(servItemId);
                itemName = itemAdditionDRO.getItemAdditionName();
            }
            Integer servItemType = wallServItemDRO.getServItemType();
            sb.append(Objects.equals(servItemType, WallItemTypeEnum.SERV_ITEM.getCode()) ? "服务项：" : "附加项：")
                    .append(itemName).append("单价：").append(NumberUtil.div(wallServItemDRO.getServItemPrice().floatValue(), 100)).append("元,")
                    .append("数量").append(wallServItemDRO.getServItemSize()).append(",")
                    .append("最低价").append(NumberUtil.div(wallServItemDRO.getPriceSaleLowest().floatValue(), 100)).append("<br>");
        });
        Integer amountPrice = wallOrderPriceAmount.getAmountPrice();
        sb.append("人工优惠").append(NumberUtil.div(wallQuotationDetail.getLaborPreferencePrice().floatValue(), 100)).append("<br>")
                .append("最终价格").append(NumberUtil.div(amountPrice.floatValue(), 100)).append("<br>")
                .append("报告书图片地址：").append(wallQuotationDetail.getIntroductionSheetImg()).append("<br>");
        if (wallQuotationDIO.isAutomaticConfirmation()) {
            log.info("墙面报价一分钟自动确认============");
            sb.append("备注：已线下和用户报价达成一致，系统自动确认线上报价");
        }
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderId(orderId);
        orderLog.setWorkId(workId);
        orderLog.setOperatorType(wallQuotationDIO.getOperatorType());
        orderLog.setOperatorTypeName(GlobalConsts.getOperatorTypeName(Objects.isNull(wallQuotationDIO.getOperatorType())
                ? GlobalConsts.OPERATE_USER_TYPE_SYSTEM : wallQuotationDIO.getOperatorType()));
        orderLog.setOperatorId(Optional.ofNullable(wallQuotationDIO.getOperatorId()).orElse(1L));
        orderLog.setOperator(Optional.ofNullable(wallQuotationDIO.getOperator()).orElse("系统"));
        orderLog.setContent(sb.toString());
        orderLog.setMasterId(orderWork.getMasterId());
        orderLog.setPlat(wallQuotationDIO.getPlat());
        orderLog.setPlatWork(orderWork.getPlatWork());
        orderLog.setManageCompanyId(orderWork.getManageCompanyId());
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setTypeName("用户确认报价");
        orderLog.setBeforeStatusName("未确认");
        orderLog.setAfterStatusName("已确认");
        orderLog.setCreateTime(new Date());
        orderLogBService.save(orderLog);
    }

    /**
     * 描述: 构建默认计算墙面价格入参
     *
     * @return {@link OrderItemTwoPriceAmountDIO }
     * @author chengguang
     * @since 2022/05/30
     */
    private OrderItemTwoPriceAmountDIO buildDefault() {

        OrderItemTwoPriceAmountDIO twoPriceAmountDIO = new OrderItemTwoPriceAmountDIO();
        twoPriceAmountDIO.setTariffOnoff(GlobalConsts.YES);
        twoPriceAmountDIO.setUntariffOnoff(GlobalConsts.NO);
        twoPriceAmountDIO.setInvoker(1);
        return twoPriceAmountDIO;
    }

    /**
     * 描述: 当前用户是否关注公众号subscribe 这个字段，1，表示关注，0表示没关注
     *
     * @param openId     开放id
     * @param thirdAppId 第三个应用程序id
     * @return boolean
     * @author chengguang
     * @since 2022/06/14
     */
    private boolean isUserSubscribe(String openId, String thirdAppId) {
        try {
            ResponseDTO<WeixinUserInfoDRO> resp = privateQrCodeListRemoteService.getWeChatUserInfo(openId, thirdAppId);
            if (resp.isSuccess() && Objects.nonNull(resp.getData())) {
                Integer subscribe = resp.getData().getSubscribe();
                return Objects.equals(subscribe, 1);
            }
        } catch (Exception ex) {
            return false;
        }
        return false;
    }


    private static <T> T resultToThrow(Supplier<ResponseDTO<T>> supplier) throws OmsBaseException {

        ResponseDTO<T> responseDTO = supplier.get();
        if (Objects.isNull(responseDTO)) {
            throw new OmsBaseException(StatusConsts.STATUS_ERROR, "获取第三方数据为空");
        }
        if (!responseDTO.isSuccess()) {
            log.error("第三方方法：调用失败：{}", responseDTO.getMessage());
            throw new OmsBaseException(responseDTO.getMessage());
        }
        return responseDTO.getData();
    }
}
